<template>
    <div class="pe-input" :class="[`pe-input-${size}`]"
        :style="{ '--pe-input-border-color': borderColor, '--pe-input-hover-border-color': disabled ? 'var(--pe-input-border-color)' : '' }">
        <div v-if="prefixSlot" class="pe-input-slot pe-input-prefix-slot">
            <slot name="prefix"></slot>
        </div>
        <div class="pe-input-wrapper" @click.stop="inputFocus">
            <span v-if="prefixIcon" class="pe-input-icon">
                <prefixIcon class="pe-icon" />
            </span>
            <input ref="peInput" class="pe-input-inner" v-model="value" :id="id"
                :type="type === 'password' ? typePassword : type" :disabled="disabled" :readonly="readonly" :placeholder="placeholder"
                :maxlength="maxlength" :autofocus="autofocus" :max="max" :min="min" :name="name" @blur="blur"
                @focus="focus" @change="change" @input="input">
            <span v-if="showWordCount" class="pe-input-count">{{ length }}{{ Number(maxlength) >= 0 ? `/${maxlength}` :
                '' }}</span>
            <span v-if="showPassword && type === 'password' && length > 0" class="pe-input-icon">
                <i v-if="typePassword === 'text'" class="pe-icon show-password" @click="typePassword = 'password'">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                        <path fill="currentColor"
                            d="M512 160c320 0 512 352 512 352S832 864 512 864 0 512 0 512s192-352 512-352m0 64c-225.28 0-384.128 208.064-436.8 288 52.608 79.872 211.456 288 436.8 288 225.28 0 384.128-208.064 436.8-288-52.608-79.872-211.456-288-436.8-288zm0 64a224 224 0 1 1 0 448 224 224 0 0 1 0-448m0 64a160.192 160.192 0 0 0-160 160c0 88.192 71.744 160 160 160s160-71.808 160-160-71.744-160-160-160">
                        </path>
                    </svg>
                </i>
                <i v-else class="pe-icon show-password" @click="typePassword = 'text'">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                        <path fill="currentColor"
                            d="M876.8 156.8c0-9.6-3.2-16-9.6-22.4-6.4-6.4-12.8-9.6-22.4-9.6-9.6 0-16 3.2-22.4 9.6L736 220.8c-64-32-137.6-51.2-224-60.8-160 16-288 73.6-377.6 176C44.8 438.4 0 496 0 512s48 73.6 134.4 176c22.4 25.6 44.8 48 73.6 67.2l-86.4 89.6c-6.4 6.4-9.6 12.8-9.6 22.4 0 9.6 3.2 16 9.6 22.4 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16-3.2 22.4-9.6l704-710.4c3.2-6.4 6.4-12.8 6.4-22.4Zm-646.4 528c-76.8-70.4-128-128-153.6-172.8 28.8-48 80-105.6 153.6-172.8C304 272 400 230.4 512 224c64 3.2 124.8 19.2 176 44.8l-54.4 54.4C598.4 300.8 560 288 512 288c-64 0-115.2 22.4-160 64s-64 96-64 160c0 48 12.8 89.6 35.2 124.8L256 707.2c-9.6-6.4-19.2-16-25.6-22.4Zm140.8-96c-12.8-22.4-19.2-48-19.2-76.8 0-44.8 16-83.2 48-112 32-28.8 67.2-48 112-48 28.8 0 54.4 6.4 73.6 19.2zM889.599 336c-12.8-16-28.8-28.8-41.6-41.6l-48 48c73.6 67.2 124.8 124.8 150.4 169.6-28.8 48-80 105.6-153.6 172.8-73.6 67.2-172.8 108.8-284.8 115.2-51.2-3.2-99.2-12.8-140.8-28.8l-48 48c57.6 22.4 118.4 38.4 188.8 44.8 160-16 288-73.6 377.6-176C979.199 585.6 1024 528 1024 512s-48.001-73.6-134.401-176Z">
                        </path>
                        <path fill="currentColor"
                            d="M511.998 672c-12.8 0-25.6-3.2-38.4-6.4l-51.2 51.2c28.8 12.8 57.6 19.2 89.6 19.2 64 0 115.2-22.4 160-64 41.6-41.6 64-96 64-160 0-32-6.4-64-19.2-89.6l-51.2 51.2c3.2 12.8 6.4 25.6 6.4 38.4 0 44.8-16 83.2-48 112-32 28.8-67.2 48-112 48Z">
                        </path>
                    </svg>
                </i>
            </span>
            <span v-if="clearable && length > 0" class="pe-input-icon" style="margin-right: 5px;">
                <i class="pe-icon pe-input-clearable" @click.stop="clear">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" data-v-ea893728="">
                        <path fill="currentColor"
                            d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896m0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336z">
                        </path>
                    </svg>
                </i>
            </span>
            <span v-if="suffixIcon" class="pe-input-icon">
                <suffixIcon class="pe-icon" />
            </span>
        </div>
        <div v-if="suffixSlot" class="pe-input-slot pe-input-suffix-slot">
            <slot name="suffix"></slot>
        </div>
        <div v-if="disabled" class="pe-disabled"></div>
    </div>
</template>

<script lang='ts' setup>
import { Component, ref, useSlots, watch } from "vue"

const value = defineModel({ type: String, default: "" })

/**
 * @param type 类型
 * @param v-model 绑定值
 * @param placeholder 输入框占位文本
 * @param disabled 是否禁用
 * @param readonly 是否只读
 * @param maxlength 同原生 maxlength 属性
 * @param show-word-count 是否显示统计字数, 只在 type 为 'text' 的时候生效
 * @param size 输入框尺寸 'default' | 'large' | 'small'
 * @param clearable 是否可以清空
 * @param autofocus 原生属性，自动获取焦点
 * @param max 原生 max 属性，设置最大值
 * @param min 原生属性，设置最小值
 * @param name 等价于原生 input name 属性
 * @param show-password 是否显示密码
 * @param id 输入框id
 */

interface Props {
    type?: 'text' | 'password' |'number',
    placeholder?: string,
    disabled?: boolean,
    readonly?: boolean,
    maxlength?: number,
    showWordCount?: boolean,
    clearable?: boolean,
    size?: 'default' | 'large' | 'small',
    autofocus?: boolean,
    max?: number,
    min?: number,
    name?: string,
    showPassword?: boolean,
    prefixIcon?: Component,
    suffixIcon?: Component,
    id?: string
}

const props = withDefaults(defineProps<Props>(), {
    type: "text",
    disabled: false,
    readonly: false,
    showWordCount: false,
    clearable: false,
    size: "default",
    autofocus: false,
    showPassword: false
})

/**
 * blur 当选择器的输入框失去焦点时触发
 * focus 当选择器的输入框获得焦点时触发
 * change 仅当 modelValue 改变时，当输入框失去焦点或用户按Enter时触发
 * input 在 Input 值改变时触发
 * clear 在点击由 clearable 属性生成的清空按钮时触发
 */
const emits = defineEmits(["blur", "focus", "change", "input", "clear"])

const length = ref<number>(0)

watch(value, newValue => {
    length.value = newValue.length
}, { immediate: true })

const typePassword = ref<string>("password")

// 检查插槽是否存在
const prefixSlot = useSlots().prefix
const suffixSlot = useSlots().suffix

// 清除事件
const clear = () => {
    value.value = ""
    peInput.value.focus();
    emits("clear")
}

// 输入框元素ref
const peInput = ref()

// 获取焦点
const inputFocus = () => {
    if (!props.disabled) {
        peInput.value.focus();
    }
}

// 边框颜色
const borderColor = ref<string>("")

// 失去焦点事件
const blur = () => {
    borderColor.value = "var(--pe-color-border)"
    emits("blur")
}

// 获取焦点事件
const focus = () => {
    borderColor.value = "var(--pe-color-primary)"
    emits("focus")
}

// 仅当 modelValue 改变时，当输入框失去焦点或用户按Enter时触发
const change = () => {
    emits("change", value.value)
}

// 在 Input 值改变时触发
const input = () => {
    emits("input", value.value)
}
</script>

<script lang="ts">
export default {
    name: "pe-input"
}
</script>